-
Notifications
You must be signed in to change notification settings - Fork 464
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Jsx ast #7286
base: master
Are you sure you want to change the base?
Jsx ast #7286
Conversation
|
||
(* | ||
* jsx-fragment ::= | ||
* | <> </> | ||
* | <> jsx-children </> | ||
*) | ||
and parse_jsx_fragment p = | ||
and parse_jsx_fragment start_pos p = |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I prefer ranges to be accurate. The location should start at the opening <
token.
compiler/syntax/src/res_printer.ml
Outdated
Doc.group | ||
(Doc.concat | ||
[ | ||
line_sep; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@shulhi this part isn't 100% correct.
I'm not familiar enough with this part of the codebase.
let z1 = <> <SectionHeader> {React.string("abc")} </SectionHeader> </>
will be formatted to
let z1 =
<>
<SectionHeader> {React.string("abc")} </SectionHeader>
</>
so I'm missing some indent here. Not sure how that part works.
Would love to hear your thoughts on this.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@nojaf I checked, the indentation is handled here,
rescript/compiler/syntax/src/res_printer.ml
Lines 2085 to 2103 in 9da9b19
let should_indent = | |
match opt_braces with | |
| Some _ -> false | |
| _ -> ( | |
ParsetreeViewer.is_binary_expression expr | |
|| | |
match vb.pvb_expr with | |
| { | |
pexp_attributes = [({Location.txt = "res.ternary"}, _)]; | |
pexp_desc = Pexp_ifthenelse (if_expr, _, _); | |
} -> | |
ParsetreeViewer.is_binary_expression if_expr | |
|| ParsetreeViewer.has_attributes if_expr.pexp_attributes | |
| {pexp_desc = Pexp_newtype _} -> false | |
| {pexp_attributes = [({Location.txt = "res.taggedTemplate"}, _)]} -> | |
false | |
| e -> | |
ParsetreeViewer.has_attributes e.pexp_attributes | |
|| ParsetreeViewer.is_array_access e) |
You might need to handle the case for Pexp_jsx_fragment
here.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks, the old code will instead have matched ParsetreeViewer.has_attributes e.pexp_attributes
. Indentation now works as before.
@@ -1000,7 +1000,7 @@ Path Objects.Rec. | |||
|
|||
Complete src/Completion.res 120:7 | |||
posCursor:[120:7] posNoWhite:[120:6] Found expr:[119:11->123:1] | |||
posCursor:[120:7] posNoWhite:[120:6] Found expr:[120:5->122:5] | |||
posCursor:[120:7] posNoWhite:[120:6] Found expr:[120:5->123:0] |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Changes like this are to be expected as the range of a fragment spans from <>
till end </>
.
posCursor:[9:56] posNoWhite:[9:55] Found expr:[9:13->9:66] | ||
JSX <SectionHeader:[9:13->9:26] > _children:9:26 | ||
posCursor:[9:56] posNoWhite:[9:55] Found expr:__ghost__[9:10->9:67] |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This ghost expression is a part of the AstHelper.make_list_expression
result.
It is no longer present in the new AST, but it also didn't serve any purpose.
I believe it is okay that this test is slightly different.
In the end the result didn't change.
compiler/ml/parsetree.ml
Outdated
(* [%id] *) | ||
(* . *) | ||
(* represents <> foo </> , the entire range is stored in the expression , we keep track of >, children and </ *) | ||
| Pexp_jsx_fragment of |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The reason the store the >
and </
token is this edge case:
https://rescript-lang.org/try?version=v12.0.0-alpha.8&module=esmodule&code=DYUwLgBA+hC8ECgCQAeCB6AVBAzmATgIYB2A5iBJuhAHzJIDeASiIQMZgB0e+AlmQAoARAFsQACyEBKAL7IU1LBEIiIASQh9S4yFVpA
If we ever want to restore comments I suppose we need the proper anchors.
Map child expressions Initial mapping of Pexp_jsx_fragment to 0 Correct location in mapping Update analysis for jsx_fragment Remove unused code Print something for ml print Commit invalid test results for reference Try improve printing Correct fragment range, try and print comments Indent jsx Process comments from children inside fragment Attach comments to fragment tags Fix comment Improve comment formatting Print single element on same line Update comment WIP: Debug More debugging Works Fix some jsx printing Fix the test Clean up Update tests with location changes
Thank you @shulhi for fixing all the remaining formatter problem of the fragment node! |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Left some comments.
Just checking: is the conversion complete in that the representation of fragments is completely moved over to the new representation?
compiler/ml/ast_mapper_to0.ml
Outdated
@@ -407,6 +407,18 @@ module E = struct | |||
| Pexp_open (ovf, lid, e) -> | |||
open_ ~loc ~attrs ovf (map_loc sub lid) (sub.expr sub e) | |||
| Pexp_extension x -> extension ~loc ~attrs (sub.extension sub x) | |||
| Pexp_jsx_fragment (o, xs, c) -> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There should be a corresponding change in ast_mapper_from0
that inverts the conversion.
Also, some extension of the test cases in tests/tools_tests/ppx/TestPpx.res
to check that back and forth conversion works fine.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Alright, I think the new tests from #7318 prove this now.
Yes, that is the idea. The parser only produces jsx_fragment and not the old representation. |
tests/tools_tests/ppx/TestPpx.res
Outdated
@@ -61,3 +61,7 @@ let eq2 = 3 === 3 | |||
|
|||
let test = async () => 12 | |||
let f = async () => (await test()) + 1 | |||
|
|||
module Fragments = { | |||
let f1 = <> </> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This should be <></>
, no? (without the space).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sounds reasonable, although I do believe this is the current behavior. (Playground)
@cristianoc, anything else you can think of for |
This could be ready to go. Is the absence of changes in |
Would you add a changelog too? Assuming this change will go ahead, and the rest of the JSX investigated in a separate PR. |
Yes, I understand. Today, I made some necessary changes to ensure the tests remained consistent.
I would recommend investigating this in the same PR. There isn't much benefit to having just the fragments part. To avoid the risk of not completing a second PR, I would suggest keeping it as one. That being said, I would like to achieve a sense of completion for the fragments before taking on more changes. |
Sure continuing jsx sounds good. |
Handle comments and printing for jsx_unary_tag
Handle comments and printing (part 2)
Hi @shulhi, Did this test ever passed for you? I'm wondering if I regressed things or not with the comments. Run |
Do you mean on this branch or master? I think comments handling need a bit more work still which I'm currently working on. I'll update you later regarding these specific tests. |
I noticed that some roundtrip tests are still losing comments on this branch. I’m wondering if this issue arose after your changes or if it still needs some work. |
Definitely needs some more work. I'm working on the JSX container tag printing/handling comments. Then, need to fix the broken tests. They are expected to fail at this point until I get everything implemented. |
Some (ExprArgument {expr; loc}) | ||
| Parsetree.JSXPropValue ({loc}, _, expr) -> | ||
let loc = {loc with loc_end = expr.pexp_loc.loc_end} in | ||
Some (ExprArgument {expr; loc}) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@shulhi I struggle a bit to grasp this part.
What should happen in the follow scenario:
<Foo bar="hey" // comment
></Foo>
Is // comment
linked to "hey"
or the entire bar="hey"
expression?
The loc created here is combining the prop name and value but is further processed with only the value expression?
This feel off, is this by design? If so, I assume you then compensate for this in res_printer
?
Would it not make more sense to either introduce a new node type or create a helper function and process the three parts (entire prop, prop name & prop value)?
This is a part of #7283.
I'm introducing
Pexp_jsx_fragment
to represent fragment syntax<></>
.I found it insightful to just try it out and see what code changes are necessary.
In short a fragment is now parsed as:
after this change it becomes:
I'll add some comment to relevant changes.